home *** CD-ROM | disk | FTP | other *** search
- library DeskManager;
-
- {---------------------------------------------------------------------
- Name: DeskManager
- Purpose: Provide direct access to the desktop list-view control
- Written by Dave Jewell, 2001.
- Based on an original idea by Jeffrey Richter.
- -----------------------------------------------------------------------}
-
- uses
- Windows, Messages, CommCtrl, DeskManMessages;
-
- {$R DeskManagerDlg.res}
-
- var
- Hook: HHook = 0; // used for message chaining
- AppWindow: hWnd = 0; // handle of application window
- DeskLV: hWnd = 0; // desktop list-view handle
-
- //------------------------------------------------------------------------------
- // Get a window to the ListView control which implements the desktop
- //------------------------------------------------------------------------------
-
- function DeskManagerListView: HWnd; stdcall; export;
- var
- buff: array [0..255] of Char;
- begin
- if DeskLV = 0 then begin
- DeskLV := GetWindow (GetWindow (FindWindow ('ProgMan', Nil), gw_Child), gw_Child);
- if DeskLV <> 0 then begin
- GetClassName (DeskLV, buff, sizeof (buff));
- if buff <> 'SysListView32' then DeskLV := 0;
- end;
-
- if DeskLV = 0 then MessageBox (0, 'Panic: Desktop ListView control not found', 'DeskManager', mb_OK);
- end;
-
- Result := DeskLV;
- end;
-
- //------------------------------------------------------------------------------
- // Get the thread ID of the Explorer thread which manages the desktop
- //------------------------------------------------------------------------------
-
- function DeskManagerShellThread: DWord; stdcall; export;
- begin
- Result := GetWindowThreadProcessID (DeskManagerListView, Nil);
- end;
-
- function HandleGetItemText (DlgWnd: hWnd; Index: Integer): Integer;
- var
- Count: Integer;
- cds: TCopyDataStruct;
- buff: array [0..255] of Char;
- begin
- Result := 0;
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
- if (Index >= 0) and (Index < Count) then begin
- buff[0] := #0;
- ListView_GetItemText (DeskManagerListView, Index, 0, buff, sizeof (buff));
- cds.dwData := DM_GetItemText;
- cds.cbData := lstrlen (buff) + 1;
- cds.lpData := @buff;
- Result := SendMessage (AppWindow, wm_CopyData, DlgWnd, Integer (@cds));
- end;
- end;
-
- function HandleGetItemPosition (DlgWnd: hWnd; Index: Integer): Integer;
- var
- pt: TPoint;
- Count: Integer;
- cds: TCopyDataStruct;
- begin
- Result := 0;
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
- if (Index >= 0) and (Index < Count) then begin
- ListView_GetItemPosition (DeskManagerListView, Index, pt);
- cds.dwData := DM_GetItemPosition;
- cds.cbData := sizeof (pt);
- cds.lpData := @pt;
- Result := SendMessage (AppWindow, wm_CopyData, DlgWnd, Integer (@cds));
- end;
- end;
-
- function HandleGetItemRect (DlgWnd: hWnd; Index: Integer): Integer;
- var
- r: TRect;
- Count: Integer;
- cds: TCopyDataStruct;
- begin
- Result := 0;
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
- if (Index >= 0) and (Index < Count) then begin
- ListView_GetItemRect (DeskManagerListView, Index, r, LVIR_Bounds);
- cds.dwData := DM_GetItemRect;
- cds.cbData := sizeof (r);
- cds.lpData := @r;
- Result := SendMessage (AppWindow, wm_CopyData, DlgWnd, Integer (@cds));
- end;
- end;
-
- //------------------------------------------------------------------------------
- // Handle a special command from the application. The wm_CopyData mechanism
- // enables the app to send us an arbitrary-sized chunk of data.
- // Achtung!: Because wm_CopyData was sent synchronously by the app, any
- // response to the client *must* be posted asynchronously.
- //------------------------------------------------------------------------------
-
- function HandleCommand (Msg, DataSize: Integer; Data: PChar): Integer;
- var
- Count: Integer;
- Index: PInteger absolute Data;
- begin
- Result := 0;
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
-
- case Msg of
- // -------- Set the caption of a desktop item
- DM_SetItemText:
- if (Index^ >= 0) and (Index^ < Count) then
- Result := Integer (ListView_SetItemText (DeskManagerListView, Index^, 0, Data + sizeof (Integer)));
- end;
- end;
-
- //------------------------------------------------------------------------------
- // This is the window proc of the hidden desk manager dialog.
- // Runs in Explorer's process context.
- //------------------------------------------------------------------------------
-
- function DeskManDlgProc (DlgWnd: hWnd; Msg, wParam, lParam: Integer): Integer; stdcall;
- var
- cds: PCopyDataStruct absolute lParam;
- begin
- Result := 0;
-
- case Msg of
-
- // -------- Get text of a designated item: wParam = index
- DM_GetItemText: Result := HandleGetItemText (DlgWnd, wParam);
-
- // -------- Get position of a designated item: wParam = index
- DM_GetItemPosition: Result := HandleGetItemPosition (DlgWnd, wParam);
-
- // -------- Get bounding rectangle for designated item: wParam = index
- DM_GetItemRect: Result := HandleGetItemRect (DlgWnd, wParam);
-
- // -------- Special command (with data block) from Application
- wm_CopyData: if HWnd(wParam) = AppWindow then Result := HandleCommand (cds^.dwData, cds^.cbData, cds^.lpData);
-
- // -------- Destroy the dialog window
- wm_Close: DestroyWindow (DlgWnd);
- end;
- end;
-
- //------------------------------------------------------------------------------
- // Implement the message hook. Runs in Explorer's process context
- //------------------------------------------------------------------------------
-
- function GetMsgProc (nCode: Integer; wParam: wParam; lParam: lParam): lParam; stdcall;
- begin
- if Hook = 0 then begin
- Hook := (PMsg (lParam))^.lParam;
- // Create the server window to service client requests
- CreateDialog (hInstance, PChar (101), 0, @DeskManDlgProc);
- // Get application window handle
- AppWindow := (PMsg (lParam))^.wParam;
- // Tell the original application that server is ready
- PostMessage (AppWindow, DM_DLLReady, 0, 0);
- end;
-
- Result := CallNextHookEx (Hook, nCode, wParam, lParam);
- end;
-
- //------------------------------------------------------------------------------
- // Initialise and inject the DLL. Runs in the client application context
- //------------------------------------------------------------------------------
-
- function DeskManagerLoad (AppWindow: hWnd): Bool; stdcall; export;
- begin
- Result := False;
- // Various safety checks...
- if (Hook = 0) and (FindWindow (Nil, 'Delphi Desktop 2001') = 0) then begin
- // Hook the desktop thread
- Hook := SetWindowsHookEx (wh_GetMessage, @GetMsgProc, hInstance, DeskManagerShellThread);
- Result := Hook <> 0;
- // If success, post a message to force DLL injection
- if Result then Result := PostThreadMessage (DeskManagerShellThread, wm_Null, AppWindow, Hook);
- end;
- end;
-
- function DeskManagerUnload: Bool; stdcall; export;
- begin
- if Hook <> 0 then Result := UnhookWindowsHookEx (Hook) else Result := False;
- Hook := 0;
- end;
-
- exports
- DeskManagerLoad,
- DeskManagerUnload,
- DeskManagerListView,
- DeskManagerShellThread;
-
- begin
- end.
-
-